package cn.anlaser.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;

import cn.anlaser.admin.BaseUser;
import cn.anlaser.entity.ParentEntity;
import cn.anlaser.form.ParentForm;
import cn.anlaser.page.QueryPage;
import cn.anlaser.page.QuerySpecification;
import cn.anlaser.repository.ParentRepository;
import cn.anlaser.service.ParentService;
import cn.anlaser.status.FlagEnum;
import cn.anlaser.utils.BeanMapper;
import cn.anlaser.utils.DynamicSpecifications;
import cn.anlaser.utils.SearchFilter;
import cn.anlaser.utils.SearchFilter.Operator;
import cn.wsalix.utils.UserUtils;

public abstract class ParentServiceImpl<Form extends ParentForm, Repository extends ParentRepository<Entity>, Entity extends ParentEntity<Entity>>
		extends CommonServiceImpl<Form, Repository, Entity> implements
		ParentService<Form, Repository, Entity> {
	@Autowired
	protected UserUtils userUtils;

	@Override
	public Entity add(Entity obj, Entity parent) {
		if (parent != null && parent.getId() != null) {
			obj.setParent(parent);
			obj.setLevel(parent.getLevel() + 1);
		}else{
			obj.setLevel(1);
		}
		obj.setCreatedDate(new Date());// DateTime.now());
		BaseUser user = userUtils.getUser();
		if (obj.getFlag() == null) {// 默认数据，全部有效。新增商品、广告、文章，默认无效，新建时设置
			obj.setFlag(FlagEnum.valid);
		}
		if (user != null) {
			obj.setCreatedBy(user.getId());
		}
		return super.add(obj);
	}

	@Override
	public Entity add(Form form, Entity parent) {
		Entity obj = BeanMapper.map(form, getEntityClazz());
		traversalAssign(form, obj);
		if (parent != null && parent.getId() != null) {
			obj.setParent(parent);
			obj.setLevel(parent.getLevel() + 1);
		} else {
			obj.setLevel(1);
		}
		obj.setCreatedDate(new Date());// DateTime.now());
		BaseUser user = userUtils.getUser();
		if (obj.getFlag() == null) {// 默认数据，全部有效。新增商品、广告、文章，默认无效，新建时设置
			obj.setFlag(FlagEnum.valid);
		}
		if (user != null) {
			obj.setCreatedBy(user.getId());
		}
		return super.add(obj);
	}

	@Transactional
	@Override
	public Entity add(Form form) {
		BaseUser user = userUtils.getUser();
		Entity obj = BeanMapper.map(form, getEntityClazz());
		traversalAssign(form, obj);
		if (form.getParentId() != null) {
			Entity parent = getRepository().findOne(form.getParentId());
			obj.setParent(parent);
			obj.setLevel(parent.getLevel() + 1);
		} else {
			obj.setLevel(1);
		}
		obj.setCreatedDate(new Date());// DateTime.now());
		if (user != null) {
			obj.setCreatedBy(user.getId());
		}
		return super.add(obj);
	}

	@Transactional
	@Override
	public Entity edit(Form entity) {
		BaseUser user = userUtils.getUser();
		Entity obj = getRepository().findOne(entity.getId());
		traversalAssign(entity, obj);
		/*
		 * obj.setLastModifiedDate(new Date());// DateTime.now()); if (user !=
		 * null) { obj.setLastModifiedBy(user.getId()); }
		 */
		return super.edit(obj);
	}

	@Transactional
	@Override
	public QueryPage<Entity> findParentTop(Form form, Pageable pageable) {
		Map<String, SearchFilter> filters = null;
		if (form == null) {
			Map<String, Object> searchParams = new HashMap<String, Object>();
			filters = SearchFilter.parse(searchParams);
		} else {
			filters = buildByForm(form);
		}
		filters.put("parent", new SearchFilter("parent.id", Operator.ISNULL,
				null));

		QuerySpecification<Entity> spec = DynamicSpecifications.bySearchFilter(
				filters.values(), getEntityClazz());

		// Sort sort = new Sort(Sort.Direction.ASC, "serNo");
		QueryPage<Entity> resPage = new QueryPage<Entity>();
		resPage.setQueryLine(spec.getQueryLine() + "&size="
				+ pageable.getPageSize() + "&orders=id" + "&direction="
				+ Sort.Direction.ASC);
		resPage.setPage(getRepository().findAll(
				spec,
				new PageRequest(pageable.getPageNumber(), pageable
						.getPageSize(), new Sort(Sort.Direction.ASC,
						new String[] { "id" }))));
		return resPage;
	}

	@Transactional
	@Override
	public QueryPage<Entity> findByParent(Form form, Pageable pageable) {
		Map<String, SearchFilter> filters = null;
		if (form == null) {
			Map<String, Object> searchParams = new HashMap<String, Object>();
			filters = SearchFilter.parse(searchParams);
		} else {
			filters = buildByForm(form);
		}
		if (form.getParentId() != null && form.getParentId() != 0) {
			filters.put("parent", new SearchFilter("parent.id", Operator.EQ,
					form.getParentId()));
		}
		QuerySpecification<Entity> spec = DynamicSpecifications.bySearchFilter(
				filters.values(), getEntityClazz());

		QueryPage<Entity> resPage = new QueryPage<Entity>();
		resPage.setQueryLine(spec.getQueryLine() + "&size="
				+ pageable.getPageSize() + "&orders=" + form.getOrders()
				+ "&direction=" + form.getDirection());
		if (form.getOrders() == null||form.getOrders().equals("")) {
			form.setOrders("id");
		}
		resPage.setPage(getRepository().findAll(
				spec,
				new PageRequest(pageable.getPageNumber(), pageable
						.getPageSize(), new Sort(form.getDirection(),
						new String[] { form.getOrders() }))));
		return resPage;
	}

	// @Cacheable(value = "parentCache")
	@Override
	public List<Entity> findParentTop(Form form) {
		Map<String, SearchFilter> filters = null;
		if (form == null) {
			Map<String, Object> searchParams = new HashMap<String, Object>();
			filters = SearchFilter.parse(searchParams);
		} else {
			filters = buildByForm(form);
		}
		filters.put("parent", new SearchFilter("parent.id", Operator.ISNULL,
				null));

		Specification<Entity> spec = DynamicSpecifications.bySearchFilter(
				filters.values(), getEntityClazz());

		Sort sort = new Sort(Sort.Direction.ASC, "serNo");
		List<Entity> resLst = getRepository().findAll(spec, sort);
		return resLst;
	}

	// @CacheEvict(value = "parentCache", key = "#form.getParentId()")
	@Override
	public List<Entity> findByParent(Form form) {
		Map<String, SearchFilter> filters = buildFilter(form);
		filters.put("parent",
				new SearchFilter("parent.id", Operator.EQ, form.getParentId()));

		Specification<Entity> spec = DynamicSpecifications.bySearchFilter(
				filters.values(), getEntityClazz());

		Sort sort = new Sort(Sort.Direction.ASC, form.getOrders());
		List<Entity> resLst = getRepository().findAll(spec, sort);
		return resLst;
	}

}
